<template>
  <div ref="wrapper" style="width: 100%; height: 100%">
    <slot></slot>
  </div>
</template>
<script>
import _ from "lodash";
export default {
  name: "SizedBox",
  model: {
    prop: "size",
    event: "change"
  },
  props: {
    size: {
      type: Object,
      default() {
        return {
          width: 0,
          height: 0
        };
      }
    },
    initTryInterval: {
      type: Number,
      default() {
        return 50;
      }
    },
    totalTryCount: {
      type: Number,
      default() {
        return 3;
      }
    }
  },
  data() {
    return {
      tryCount: 0,
      tryInterval: 0,
      timeout: null,
      myObserver: null
    };
  },
  filters: {
    normalize: function(value) {
      if (value > 0) {
        return value + "px";
      }
      return "auto";
    }
  },
  mounted() {
    window.addEventListener("resize", this.smartAdjust);
    this.observer();
  },
  beforeDestroy() {
    window.removeEventListener("resize", this.smartAdjust);
    this.myObserver.disconnect();
  },
  methods: {
    observer() {
      let vm = this;
      let parentElement = _.get(vm.$refs, ["wrapper", "parentElement"]);
      this.myObserver = new ResizeObserver(
        _.throttle(entries => {
          let width = entries[0].contentRect.width;
          let height = entries[0].contentRect.height;
          vm.$emit("change", { width, height });
        }),
        500
      );
      this.myObserver.observe(parentElement);
    },
    update() {
      this.smartAdjust();
    },
    smartAdjust() {
      if (!_.isNil(this.timeout)) {
        clearTimeout(this.timeout);
        this.timeout = null;
      }
      this.$emit("change", { width: 0, height: 0 });
      this.$nextTick(() => {
        this.tryInterval = this.initTryInterval;
        this.tryCount = this.totalTryCount;
        this.tryAdjust();
      });
    },
    onResize() {
      let vm = this;
      vm.tryCount--;
      let parentElement = _.get(vm.$refs, ["wrapper", "parentElement"]);

      if (parentElement) {
        let width = parentElement.offsetWidth;
        let height = parentElement.offsetHeight;
        let size = { width, height };
        if (this.tryCount <= 0) {
          this.$emit("change", size);
        }
      }
    },
    tryAdjust() {
      this.onResize();
      if (this.tryCount > 0) {
        this.timeout = setTimeout(() => {
          this.tryAdjust();
        }, this.tryInterval);
        this.tryInterval *= 2;
      }
    }
  }
};
</script>

<style scoped>
.mask {
  display: block;
  z-index: 0;
}
.wrapper {
  position: relative;
}
</style>
